<template>
  <div class="container">
    <!-- 固定导航 -->
    <van-nav-bar fixed left-arrow @click-left="$router.back()" :title="this.$route.query.nickName"></van-nav-bar>

    <!-- 聊天主体区域 -->
    <div class="chat-list" ref="refList">
      <div
          v-for="(item) in list"

          :class="item.senderId === item.userId ? 'right' : 'left'"
          class="chat-item">
        <!-- template是一个逻辑上的容器，页面在渲染时，它不会产生dom -->
        <template v-if="item.senderId === item.userId">
          <div class="chat-pao" @click="isRight=!isRight">
            <van-image v-if="item.contentType==='image'" fit="cover" :src="item.content"/>
            <div v-else style="text-align:left">{{item.msg}}</div>
            <span></span>
          </div>
          <van-image fit="cover" round :src="item.senderAvatar" />
        </template>
        <template v-else>
          <van-image fit="cover" round :src="$route.query.url" @click="$router.push('/perInfo')" />
          <div class="chat-pao" @click="isRight=!isRight">
            <van-image style="width: 100%;height: 100%;" v-if="item.contentType==='image'" fit="cover" :src="item.content"/>
            <div v-else style="text-align:left">{{item.msg}}</div>
            <span></span>
          </div>
        </template>
      </div>
    </div>

    <!-- 对话区域 说话-->
    <div class="reply-container van-hairline--top">
      <div class="row">
        <van-icon name="add-o" size="35" @click="checked=!checked;photoShow=true"/>
        <van-field v-model.trim="word"
                   type="textarea"
                   autosize
                   @focus="photoShow=false"
                   @input="send_hc" placeholder="说点什么...">
        </van-field>
        <van-button
            type="info"
            class="send"
            size="info"
            @click="send()"
        >发送</van-button>
      </div>
      <div class="photoShow" v-show="photoShow">
        <van-uploader v-model="fileList" multiple :after-read="afterRead" />
      </div>
      <input type="file" hidden @change="hChangeImage" ref="refFile"/>
    </div>
  </div>
</template>

<script>
import { mapGetters, mapState } from 'vuex'

export default {
  name: "UserChat",
  data () {
    return {
      list: [ // 对话记录
        { senderId: '1',userId: '1',name: 'xz',senderAvatar:'/images/background/leaf.jpg', msg: '你好！', timestamp: Date.now() },
        { senderId: '1',userId: '2',name: 'xz',senderAvatar:'https://s1.328888.xyz/2022/09/05/1xVDF.png', msg: '你好！', timestamp: Date.now() },
        // { senderId: '1',userId: '1',name: 'me',senderAvatar:'/images/background/leaf.jpg', msg: '在孩子面前不要再扮演全知全能的父母角色，适当地装傻，不再讲究权威，沟通时候要培养孩子的权威和尊严，否则孩子凭什么买你的帐?许多孩子在叛逆的时期是对父母横挑鼻子竖挑眼的示弱。', timestamp: Date.now() },
        // { senderId: '1',userId: '2',name: 'xz',senderAvatar:'https://s1.328888.xyz/2022/09/05/1xVDF.png', msg: '我有点晕了', timestamp: Date.now() },
        // { senderId: '1',userId: '2',name: 'me',senderAvatar:'https://s1.328888.xyz/2022/09/05/1xVDF.png',msg: '我是一个伟大的程序员', timestamp: Date.now() },
        // { senderId: '1',userId: '1',name: 'xz',senderAvatar:'https://s1.328888.xyz/2022/09/05/1x2ro.png', msg: '哦，你cv一定很熟！', timestamp: Date.now() },
        // { senderId: '1',userId: '1',name: 'xz',senderAvatar:'https://s1.328888.xyz/2022/09/05/1x2ro.png', msg: '您好，怎么和青春期叛逆的孩子沟通 呢？', timestamp: Date.now() },
        // { senderId: '1',userId: '2',name: 'me',senderAvatar:'https://s1.328888.xyz/2022/09/05/1xVDF.png', msg: '在孩子面前不要再扮演全知全能的父母角色，适当地装傻，不再讲究权威，沟通时候要培养孩子的权威和尊严，否则孩子凭什么买你的帐?许多孩子在叛逆的时期是对父母横挑鼻子竖挑眼的示弱。', timestamp: Date.now() },
        // { senderId: '1',userId: '1',name: 'xz',senderAvatar:'https://s1.328888.xyz/2022/09/05/1x2ro.png', msg: '我有点晕了', timestamp: Date.now() },
        // { senderId: '1',userId: '2',name: 'me',senderAvatar:'https://s1.328888.xyz/2022/09/05/1xVDF.png', msg: '我是一个伟大的程序员', timestamp: Date.now() },
        // { senderId: '1',userId: '1',name: 'xz',senderAvatar:'https://s1.328888.xyz/2022/09/05/1x2ro.png', msg: '哦，你cv一定很熟！', timestamp: Date.now() }
      ],
      // Uploader 根据文件后缀来判断是否为图片文件
      // 如果图片 URL 中不包含类型信息，可以添加 isImage 标记来声明
      fileList: [],
      isRight: false,
      word: '',
      checked: false,
      photoShow: false,
      // 上滑结束取消语音发送的坐标变量
      posStart: 0, // 初始化起点坐标
      posEnd: 0, // 初始化终点坐标
      posMove: 0, // 初始化滑动坐标
      btnElem: null,
      value: '按住 说话',
      // 计时器相关参数
      time: '',
      // 分，秒
      minute: 0,
      second: 0, // 秒
      timeShow: false,
      jianting: 0, // 防止创建多个监听函数
      contentType: 'word',
      maikef: true,
      pageNum: 1,
      pageSize: 13,
      total: 20,
      scollRight: true
    }
  },
  watch: {
    checked: {
      // username 监听输入框输入
      handler (newValue, oldValue) {
        if (this.checked === true) {
          this.saveYyxiaoxi()
        }
      }
    }
  },
  computed: {
    ...mapState(['userinfo']),
    user () {
      return this.$store.state.userInfo
    }
  },
  created () {
    // 设置监听函数
    this.timer = setInterval(() => {
      console.log(Date.now())
    }, 1000)
    // 1. 创建webscoket连接
    // 格式：io(url, 参数)
    // http://47.114.163.79:3003
    // http://ttapi.research.itcast.cn
    // ${this.$route.query.chatRoom}/${this.user.id}/${this.user.name}/${this.user.photo}/
    // this.socketio = io('http://47.114.163.79:3003'
    // // var url = `ws://192.168.100.33:8080/${this.$route.query.chatRoom}/${this.user.id}/${this.user.name}/${this.user.photo}/socket.io/`
    // // this.socketio = io(url
    //   // /${this.user.id}/${this.user.name}/${this.user.photo}/

    // )
    if ('WebSocket' in window) {
      this.initWebSocket()
    } else {
      alert('当前浏览器不支持websocketio连接')
    }
    // this.socketio.on('concat', () => {
    //   console.log('连接成功')
    //   // 小爱同学打招呼
    //   this.list.push({
    //     name: 'xz', msg: '你好，你的小爱同学上线了！', timestamp: Date.now()
    //   })
    //   this.scrollToBottom()
    // })

    // this.socketio.on('message', (obj) => {
    //   console.log('从服务器发回来的数据', obj)
    //   // {msg: "我的长的好看!", timestamp: 1602229081886}
    //   const msg = {
    //     ...obj, name: 'xz'
    //   }
    //   this.list.push(msg)
    //   this.scrollToBottom()
    // })
  },
  // 组件销毁时，关闭与服务器的连接
  destroyed () {
    // 组件销毁时，关闭与服务器的连接
    if (this.socketio) {
      // this.socketio.close()
      // this.socketio.onclose = function () {
      //   console.log('连接已关闭...')
      // }
      this.socketio.close() // 离开路由之后断开websocket连接
    }

    clearInterval(this.timer)
  },
  mounted () {
    this._Chatrecord()
    this.scrollTop()
  },
  methods: {
    afterRead(file) {
      // 此时可以自行将文件上传至服务器
      console.log(file);
    },
    scrollTop () {
      this.dom = this.$refs.refList
      this.dom.onscroll = () => {
        console.log(this.list, this.total)
        if (this.list.length >= this.total) {
          return
        }
        if (this.dom.scrollTop < 50) {
          if (this.scollRight) {
            return
          }
          this.scollRight = true
          setTimeout(() => {
            this.pageSize = this.pageSize + 10
            this._Chatrecord()
            this.dom.scrollTop = this.dom.scrollTop + this.$refs.refList.clientHeight
            console.log('111this.dom.scrollTop', this.dom.scrollTop, this.$refs.refList.clientHeight)
          }, 1000)
        }
      }
    },
    async _Chatrecord () { // 查询聊天记录
      const data = {
        receiverId: this.user.id,
        receiverName: this.user.name,
        chatRoom: this.$route.query.chatRoom,
        pageNum: this.pageNum,
        pageSize: this.pageSize
      }
      try {
        const res = await Chatrecord(data)
        console.log(res)
        if (res.data.code === 200) {
          this.total = res.data.data.total
          this.list = res.data.data.rows ? res.data.data.rows.map(item => {
            item.senderAvatar = this.Common.api + item.senderAvatar
            return {
              ...item,
              senderTime: item.createTime
            }
          }).reverse() : [] // 倒序 最新消息在下面
          this.scollRight = false
          if (this.pageSize < 15) {
            console.log('111')
            this.scrollToBottom()
          }
        } else {
          this.$toast.fail(res.data.msg)
        }
      } catch (err) {
        console.log(err)
        this.$toast.fail('网络错误，请稍后重试')
      }
    },
    initWebSocket () {
      let protocol = 'ws'
      if (location.protocol === 'https:') {
        protocol = 'wss'
      }
      // const url = `${protocol}://192.168.100.33:8080/websocket/${this.$route.query.chatRoom}/${this.user.id}/${this.user.name}${this.user.photo}`
      // console.log(`${this.$route.query.chatRoom}/${this.user.id}/${this.user.name}${this.user.photo}`)
      console.log(encodeURI(this.user.name))
      // var url = 'ws://192.168.100.33:8080' ?senderAvatar=${this.Common.api + this.user.photo}
      var url = protocol + '://192.168.100.33:8080' + `/websocket/${this.$route.query.chatRoom}/${this.user.id}/${encodeURI(this.user.name)}`
      // decodeURI
      this.socketio = new WebSocket(url)
      // 建立连接
      this.socketio.onopen = function () {
        // this.socketio.send('已经上线了')
        console.log('已经连通了websocket')
      }
      // 接收消息
      // 接收后台服务端的消息    接收到消息
      this.socketio.onmessage = (evt) => {
        console.log('数据已接收:', evt)
        const obj = JSON.parse(evt.data)
        console.log('obj', obj)
        this.list.push(obj)
        this.scrollToBottom()
      }
      // 连接建立失败重连
      this.socketio.onerror = this.websocketonerror
      // 关闭
      this.socketio.onclose = this.websocketclose
    },
    websocketonerror () { // 连接建立失败重连
      console.log('websocket连接断开')
      this.initWebSocket()
    },
    websocketclose (e) { // 关闭
      console.log('断开连接', e)
    },
    uploadPhone () {
      this.$refs.refFile.click()
    },
    async hChangeImage () {
      // 获取用户选中的文件
      console.dir(this.$refs.refFile)
      // this.$refs.refFile 获取对input type="file" 的引用
      // 用户选中文件之后，它会自动放在 files 集合中
      // files[0] : 是用户选中的第一个文件
      const file = this.$refs.refFile.files[0]
      // console.log('file')
      // console.dir(file)
      if (!file) {
        return
      }
      try {
        // 上传文件
        const fd = new FormData()
        // fd.append('avatarfile', file) // photo是接口需要的参数名，file是文件
        fd.append('file', file) // photo是接口需要的参数名，file是文件
        fd.append('type', 1)

        const result = await setAvater(fd)
        console.log(result)
        // 调用接口，上传这个文件
        // this.$store.commit('mUpdatePhoto', result.data.url)
        // this.$toast.success('操作成功')
        // this.list.push({ name: 'me', msg: `${this.Common.api}${result.data.url}`, timestamp: Date.now() })
        if (result.data.code === 200) {
          this.photoShow = false
          this.sendPhoto(result.data.data.url)
        } else {
          this.$toast.fail(result.data.msg)
        }
        // this.list.push({ name: 'me', msg: `${result.data.data.url}`, timestamp: Date.now() })
        // this.scrollToBottom()
      } catch (err) {
        console.log(err)
        this.$toast.fail('操作失败')
      }
    },
    _timeChange (val) {
      return timeChange(val)
    },
    saveYyxiaoxi () {
      // 获取语音发送变量
      console.log('ahsadgh1')
      if (this.jianting === 0) {
        this.btnElem = document.getElementById('messageBtn')
        this.initEvent()
      }
      this.jianting = 1
    },
    reset () { // 重置
      clearInterval(this.time)
      this.time = null
      this.hour = 0
      this.minute = 0
      this.second = 0
    },
    // 滚动事件
    scrollToBottom () {
      this.$nextTick(() => {
        const dom = this.$refs.refList
        // scrollTop 是dom元素的属性，可以去手动设置
        //   它表示当前dom元素中的滚动条距离元素顶部的距离
        dom.scrollTop = dom.scrollHeight
      })
    },
    send_hc () { // 监听回车事件
      document.onkeydown = (e) => {
        const _key = window.event.keyCode
        console.log(_key)
        //! this.clickState是防止用户重复点击回车
        if (_key === 13) {
          this.send()
        }
      }
    },
    send () {
      if (this.word === '') {
        return
      }
      // 1. 把我要说的话发给服务器接口
      console.log(this.word)
      
      this.contentType = 'word'
      
      let message = {}
      message.senderId = 1
      message.userId = 1
      message.name = 'Charlie'
      message.senderAvatar = '/images/background/leaf.jpg'
      message.msg = this.word
      message.timestamp = Date.now()
      // 2.在本地添加消息
      this.list.push(message)
      this.scrollToBottom()
      // 3. 清空
      this.word = ''
    },
    sendPhoto (url) {
      this.contentType = 'image'
      const data = {
        chatType: 'personal_chat',
        receiverId: this.$route.query.id,
        receiverName: this.$route.query.friendName,
        senderAvatar: this.Common.api + this.user.photo,
        content: url,
        contentType: this.contentType
      }
      this.socketio.send(JSON.stringify(data))
      // 2.在本地添加消息
      // this.list.push({ name: 'me', msg: this.word, timestamp: Date.now() })
      // this.scrollToBottom()
      // 3. 清空
      // this.word = ''
    },
  }
}
</script>

<style lang="scss" scoped>
.send {
  width: 40px;
  height: 28px;
  color: #fff;
  font-size: 12px;
  display: flex;
  margin: 0 10px;
  border-radius: 4px;
  align-items: center;
  justify-content: center;
  background: #2a78f4;
}

.container {
  height: 100%;
  width: 100%;
  position: absolute;
  left: 0;
  top: 0;
  box-sizing: border-box;
  background:#fafafa;
  padding: 46px 0 50px 0;
  .chat-list {
    height: 100%;
    overflow-y: scroll;
    .chat-item{
      padding: 10px;
      .van-image{
        vertical-align: top;
        width: 40px;
        height: 40px;
      }
      .chat-pao{
        vertical-align: top;
        display: inline-block;
        min-width: 40px;
        max-width: 70%;
        min-height: 40px;
        line-height: 38px;
        border: 0.5px solid #c2d9ea;
        border-radius: 4px;
        position: relative;
        padding: 0 10px;
        background-color: #e0effb;
        word-break: break-all;
        font-size: 14px;
        color: #333;
        ::v-deep.van-image{
          width: 100%;height: 100%;
        }
        &::before{
          content: "";
          width: 10px;
          height: 10px;
          position: absolute;
          top: 12px;
          border-top:0.5px solid #c2d9ea;
          border-right:0.5px solid #c2d9ea;
          background: #e0effb;
        }
      }
    }
  }
}
.chat-item.right{
  text-align: right;
  .chat-pao{
    margin-left: 0;
    margin-right: 15px;
    &::before{
      right: -6px;
      transform: rotate(45deg);
    }
    span{
      right: 0;
      left: auto;
    }
  }
}
.chat-item.left{
  text-align: left;
  .chat-pao{
    margin-left: 15px;
    margin-right: 0;
    &::before{
      left: -5px;
      transform: rotate(-135deg);
    }
  }
}
.chat-pao{
  span{
    position: absolute;
    width: fit-content; // 内容宽度
    // min-width: 2.2rem;
    // text-align: center;
    height: 0.4rem;
    line-height: 0.4rem;
    bottom: -18px;
    left: 0;
    background: #CECECE;
    color: #fff;
    font-size: 0.22rem;
    font-family: PingFang SC;
    font-weight: 400;
  }
}
.reply-container {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  background: #fff;
  z-index: 9999;
  div{
    height: 44px;
  }
  .row{
    box-sizing: border-box;
    display: flex;
    align-items: center;
    input{
      height: 0.6rem;
    }
  }
  .photoShow{
    height: 120px;
    display: flex;
    padding-left: 5px;
    font-size: 0.24rem;
    font-family: PingFang SC;
    font-weight: 400;
    color: #1B1E27;
    i{
      vertical-align: middle;
      font-size: 0.4rem;
    }
  }
  .row{
    i{
      display: inline-block;
      width: 10%;
      text-align: center;
    }
  }
  .btn{
    border: 0;
    width: 80%;
    background: #3964E6;
    border-radius: 0.16rem;
    font-size: 0.24rem;
    font-family: PingFang SC;
    font-weight: 400;
    color: #FFFFFF;
  }
  ::v-deep.van-cell{
    display: inline-block;
    box-sizing: border-box;
    vertical-align: middle;
    width: 80%;
  }
}
// 时间弹层
.van-popup{
  width: 45%;
  height: 3rem;
  background: rgba(0, 0, 0, .7);
  border-radius: 0.2rem;
  color: #fff;
  text-align: center;
  div{
    margin: 0.4rem;
    font-size: 0.3rem;
    font-family: PingFang SC;
    font-weight: 400;
    &:nth-child(1){
      font-size: 0.6rem;
    }
  }
}
</style>
